home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-19 / iritsm3s.zip / POLY3D.C < prev    next >
C/C++ Source or Header  |  1992-03-03  |  25KB  |  733 lines

  1. /*****************************************************************************
  2. *   Program to draw 3D object as wireframe from    any ortographic view         *
  3. * Options:                                     *
  4. * 1. -c : Object is closed. If object is closed each edge is shared by two   *
  5. *         polygons and therefore can bedrawn only once.                 *
  6. * 2. -e #Edges : If the edges are order is specific way (like in DrawFn3D)   *
  7. *         and only the k first edges of each polygons are to be displayed    *
  8. *      use this option as -e k.                         *
  9. * 3. -i : Internal edges. IRIT solid modeller may generate edges, which one  *
  10. *      may not want to see (default). -i will draw all of them.         *
  11. * 4. -m : More flag, to print more imformation on input/errors.             *
  12. *         Note all messages goes to STDOUT (not stderr!) as this program     *
  13. *      works in graphic mode, and we can redirect stdout to a file.       *
  14. * 5. -n : Draw vertices normals if the data has them, otherwise ignore.      *
  15. * 6. -M : draw surfaces Mesh and curves control polygon.             *
  16. * 7. -I n : number of isolines for a given surface.                 *
  17. * 8. -P : generate polygon for surfaces.                     *
  18. * 9. -S n : log based 2 of number of samples per curve.                 *
  19. * 10. -f FineNess : log based 2 of the fineness control of surface to        *
  20. *         polygon subdivision.                             *
  21. * 11. -4 : force 4 polygons per flat. Otherwise two.                 *
  22. * 12. -z : Print current version, and some helpfull data.             *
  23. *                                         *
  24. * Note some of those options way be permanently set to a different default   *
  25. * using the configuration file "Poly3D.cfg"                     *
  26. *                                         *
  27. * Usage:                                     *
  28. *   Poly3D [-c] [-m] [-i] [-e #Edges] [-n] [-N] [-M] [-I n] [-P] [-S n]         *
  29. *                    [-f FineNess] [-4] [-z] Files        *
  30. *                                         *
  31. * Written by:  Gershon Elber                Ver 3.0, Aug 1990    *
  32. *****************************************************************************/
  33.  
  34. #ifdef __MSDOS__
  35. #include <stdlib.h>
  36. #include <conio.h>
  37. #include <dos.h>
  38. #include <graphics.h>
  39. #include <alloc.h>
  40. #endif /* __MSDOS__ */
  41.  
  42. #include <stdio.h>
  43. #include <string.h>
  44. #include <time.h>
  45. #include "program.h"
  46. #include "getarg.h"
  47. #include "genmat.h"
  48. #include "interact.h"
  49. #include "graphgen.h"
  50. #include "config.h"
  51.  
  52. #ifdef __TURBOC__      /* Malloc debug routine - only on TC++ 1.0 and above. */
  53. #define __DEBUG_MALLOC__
  54. #endif /* __TURBOC__ */
  55.  
  56. #ifdef __MSDOS__
  57. #include "matherr.h"
  58. #endif /* __MSDOS__ */
  59.  
  60. #ifdef __MSDOS__
  61. extern unsigned int _stklen = 32766;         /* Increase default stack size. */
  62. #endif /* __MSDOS__ */
  63.  
  64. #ifdef NO_CONCAT_STR
  65. static char *VersionStr =
  66.     "Poly3D        Version 3.0,    Gershon Elber,\n\
  67.      (C) Copyright 1989/90/91 Gershon Elber, Non commercial use only.";
  68. #else
  69. static char *VersionStr = "Poly3D    " VERSION ",    Gershon Elber,    "
  70.     __DATE__ ",   " __TIME__ "\n"
  71.     "(C) Copyright 1989/90/91 Gershon Elber, Non commercial use only.";
  72. #endif /* NO_CONCAT_STR */
  73.  
  74. static char *CtrlStr =
  75.     "poly3d c%- m%- i%- e%-#Edges!d n%- N%- M%- P%- I%-#IsoLines!d S%-#SampPerCrv!d f%-FineNess!d 4%- z%- DFiles!*s";
  76.  
  77. static int
  78.     GlblNormalLenAux = NORMAL_DEFAULT_LENGTH,
  79.     GlblFineNess    = 5,
  80.     GlblFourPerFlat = FALSE;
  81.  
  82. /* The following are setable variables (via configuration file poly3d.cfg).  */
  83. int
  84. #if defined(__MSDOS__) || defined(DJGCC)     /* Defaults for MSDOS intr_lib. */
  85.     GlblWindowFrameWidth = 8,
  86.     GlblViewFrameColor   = INTR_COLOR_RED,
  87.     GlblViewBackColor    = INTR_COLOR_BLACK,
  88.     GlblTransFrameColor  = INTR_COLOR_GREEN,
  89.     GlblTransBackColor   = INTR_COLOR_BLACK,
  90.     GlblStatusFrameColor = INTR_COLOR_RED,
  91.     GlblStatusBackColor  = INTR_COLOR_BLACK,
  92.     GlblInputFrameColor  = INTR_COLOR_RED,
  93.     GlblInputBackColor   = INTR_COLOR_BLACK,
  94.     GlblDrawHeader       = FALSE,
  95.     GlblSmoothTextScroll = FALSE,
  96.     GlblIntrSaveMethod   = INTR_SAVE_DISK,
  97.     GlblMouseSensitivity = 10,         /* Sensitivity control of mouse device. */
  98.     GlblJoystickExists   = FALSE,
  99. #endif /*__MSDOS__ || DJGCC */
  100. #ifdef __MSDOS__
  101.     GlblGraphDriver      = DETECT,
  102. #endif /* __MSDOS__ */
  103.     GlblWasCtrlBrk       = FALSE,
  104.     GlblMouseExists      = TRUE,
  105.     GlblTransformMode    = TRANS_SCREEN,      /* Screen, Object trans. mode. */
  106.     GlblViewMode         = VIEW_ORTHOGRAPHIC,        /* Persp, Ortho etc. */
  107.     GlblDepthCue         = TRUE,            /* Activate depth cueing. */
  108.     GlblDrawSolid        = FALSE,     /* Use hardware Z buffer rendering. */
  109.     GlblInternal         = FALSE,
  110.     GlblDoGraphics       = TRUE,/* Control if running in graphics/text mode. */
  111.     GlblMore             = FALSE,
  112.     GlblNumEdges         = 0,
  113.     GlblDrawVNormal      = FALSE,
  114.     GlblDrawPNormal      = FALSE,
  115.     GlblClosedObject     = FALSE,
  116.     GlblDrawSurfaceMesh  = FALSE,
  117.     GlblDrawSurfacePoly  = FALSE,
  118.     GlblNumOfIsolines    = DEFAULT_NUM_OF_ISOLINES,
  119.     GlblSamplesPerCurve  = DEFAULT_SAMPLES_PER_CURVE;
  120.  
  121. static char
  122.     *BGIDriverPath = NULL,
  123.     *SVGANameMode  = NULL;
  124.  
  125. char
  126. #ifdef __GL__
  127.     /* Preferance position and size of view and transformation windows. */
  128.     *GlblTransPrefPos = "455, 640, 520, 965",
  129.     *GlblViewPrefPos  = "1,   450, 520, 965",
  130. #endif /* __GL__ */
  131. #if defined(__MSDOS__) || defined(DJGCC)     /* Defaults for MSDOS intr_lib. */
  132.     *GlblViewWndwPos   = "0.02, 0.02, 0.72, 0.98",
  133.     *GlblTransWndwPos  = "0.75, 0.02, 0.98, 0.98",
  134.     *GlblStatusWndwPos = "",
  135.     *GlblInputWndwPos  = "",
  136.     *GlblIntrSaveDisk  = "d:\\",
  137. #endif /* __MSDOS__ || DJGCC */
  138.     GlblFirstDataFileName[PATH_NAME_LEN];  /* Hold name of first data file. */
  139.  
  140. static long SaveTotalTime;
  141.  
  142. MatrixType CrntViewMat;                /* This is the current view! */
  143.  
  144. RealType GlblNormalLen = 0.0;             /* Scaler for normals if drawn. */
  145.  
  146. static ConfigStruct SetUp[] =
  147. {
  148. #if defined(__MSDOS__) || defined(DJGCC)     /* Defaults for MSDOS intr_lib. */
  149.   { "Joystick",        (VoidPtr) &GlblJoystickExists,    SU_BOOLEAN_TYPE },
  150.   { "Mouse",        (VoidPtr) &GlblMouseExists,    SU_BOOLEAN_TYPE },
  151.   { "MouseSensitivity",    (VoidPtr) &GlblMouseSensitivity,SU_INTEGER_TYPE },
  152.   { "WndwWidth",    (VoidPtr) &GlblWindowFrameWidth,SU_INTEGER_TYPE },
  153.   { "WndwHeader",    (VoidPtr) &GlblDrawHeader,    SU_BOOLEAN_TYPE },
  154.   { "WndwViewClr",    (VoidPtr) &GlblViewFrameColor,    SU_INTEGER_TYPE },
  155.   { "WndwTransClr",    (VoidPtr) &GlblTransFrameColor,    SU_INTEGER_TYPE },
  156.   { "WndwViewPos",    (VoidPtr) &GlblViewWndwPos,    SU_STRING_TYPE },
  157.   { "WndwTransPos",    (VoidPtr) &GlblStatusWndwPos,    SU_STRING_TYPE },
  158.   { "WndwBackSave",    (VoidPtr) &GlblIntrSaveMethod,    SU_INTEGER_TYPE },
  159.   { "WndwBackSavePath",    (VoidPtr) &GlblIntrSaveDisk,    SU_STRING_TYPE },
  160. #endif /* __MSDOS__ || DJGCC */
  161. #ifdef __MSDOS__
  162.   { "SVGANameMode",    (VoidPtr) &SVGANameMode,    SU_STRING_TYPE },
  163.   { "BGIDriverPath",    (VoidPtr) &BGIDriverPath,    SU_STRING_TYPE },
  164.   { "GraphDriver",    (VoidPtr) &GlblGraphDriver,    SU_INTEGER_TYPE },
  165. #endif /* __MSDOS__ */
  166. #ifdef __GL__
  167.   { "TransPrefPos",    (VoidPtr) &GlblTransPrefPos,    SU_STRING_TYPE },
  168.   { "ViewPrefPos",    (VoidPtr) &GlblViewPrefPos,    SU_STRING_TYPE },
  169. #endif /* __GL__ */
  170.   { "FineNess",        (VoidPtr) &GlblFineNess,    SU_INTEGER_TYPE },
  171.   { "FourPerFlat",    (VoidPtr) &GlblFourPerFlat,    SU_BOOLEAN_TYPE },
  172.   { "ViewMode",        (VoidPtr) &GlblViewMode,    SU_INTEGER_TYPE },
  173.   { "TransMode",    (VoidPtr) &GlblTransformMode,    SU_INTEGER_TYPE },
  174.   { "ClosedObject",    (VoidPtr) &GlblClosedObject,    SU_BOOLEAN_TYPE },
  175.   { "DepthCue",        (VoidPtr) &GlblDepthCue,    SU_BOOLEAN_TYPE },
  176.   { "DrawSolid",    (VoidPtr) &GlblDrawSolid,    SU_BOOLEAN_TYPE },
  177.   { "Internal",        (VoidPtr) &GlblInternal,    SU_BOOLEAN_TYPE },
  178.   { "More",        (VoidPtr) &GlblMore,        SU_BOOLEAN_TYPE },
  179.   { "NormalLength",    (VoidPtr) &GlblNormalLenAux,    SU_INTEGER_TYPE },
  180.   { "DrawVNormal",    (VoidPtr) &GlblDrawVNormal,    SU_BOOLEAN_TYPE },
  181.   { "DrawPNormal",    (VoidPtr) &GlblDrawPNormal,    SU_BOOLEAN_TYPE },
  182.   { "NumOfEdges",    (VoidPtr) &GlblNumEdges,    SU_INTEGER_TYPE },
  183.   { "NumOfIsolines",    (VoidPtr) &GlblNumOfIsolines,    SU_INTEGER_TYPE },
  184.   { "SamplesPerCurve",    (VoidPtr) &GlblSamplesPerCurve,    SU_INTEGER_TYPE },
  185.   { "DrawSurfaceMesh",    (VoidPtr) &GlblDrawSurfaceMesh,    SU_BOOLEAN_TYPE },
  186.   { "DrawSurfacePoly",    (VoidPtr) &GlblDrawSurfacePoly,    SU_BOOLEAN_TYPE } };
  187.  
  188. #define NUM_SET_UP    (sizeof(SetUp) / sizeof(ConfigStruct))
  189.  
  190. static IPObjectStruct *MainGetDataFiles(char **DataFileNames, int NumOfDataFiles);
  191. static IPPolygonStruct *Curve2Polylines(CagdCrvStruct *Crv);
  192. static IPPolygonStruct *Surface2Polylines(CagdSrfStruct *Srf);
  193.  
  194. /*****************************************************************************
  195. * Main routine - Read Parameter    line and do what you need...             *
  196. *****************************************************************************/
  197. void
  198. #ifdef __MSDOS__
  199. cdecl        /* So we can use -rp in Borland 3.0 (parameters in registers.). */
  200. #endif /* __MSDOS__ */
  201. main(int argc, char **argv)
  202. {
  203.     int Error,
  204.     EdgesFlag = FALSE,
  205.     VerFlag = FALSE,
  206.     IsoLinesFlag = FALSE,
  207.     SamplesPerCurveFlag = FALSE,
  208.     NumFiles = 0,
  209.     FineNessFlag = FALSE;
  210.     char
  211.     **FileNames = NULL;
  212.     IPObjectStruct *PObjects;
  213.  
  214.     SaveTotalTime = time(NULL);
  215.  
  216. #ifdef __MSDOS__
  217.     ctrlbrk((int cdecl (*)()) MyExit);              /* Kill process if ^C. */
  218. #endif /* __MSDOS__ */
  219.  
  220. #ifdef __MSDOS__
  221.     MathErrorSetUp(ME_KILL, NULL);     /* Kill process if math error occurs! */
  222. #endif /* __MSDOS__ */
  223.  
  224.     Config("poly3d", SetUp, NUM_SET_UP);     /* Read config. file if exists. */
  225.  
  226.     if ((Error = GAGetArgs(argc, argv, CtrlStr,
  227.         &GlblClosedObject, &GlblMore, &GlblInternal, &EdgesFlag,
  228.         &GlblNumEdges, &GlblDrawVNormal, &GlblDrawPNormal,
  229.         &GlblDrawSurfaceMesh, &GlblDrawSurfacePoly,
  230.         &IsoLinesFlag, &GlblNumOfIsolines,
  231.         &SamplesPerCurveFlag, &GlblSamplesPerCurve,
  232.         &FineNessFlag, &GlblFineNess,
  233.         &GlblFourPerFlat, &VerFlag, &NumFiles, &FileNames)) != 0) {
  234.     GAPrintErrMsg(Error);
  235.     GAPrintHowTo(CtrlStr);
  236.     exit(1);
  237.     }
  238.  
  239.     if (VerFlag) {
  240.     fprintf(stderr, "\n%s\n\n", VersionStr);
  241.     GAPrintHowTo(CtrlStr);
  242.     ConfigPrint(SetUp, NUM_SET_UP);
  243.     exit(0);
  244.     }
  245.  
  246.     if (!NumFiles) {
  247.     fprintf(stderr, "No data file names where given, exit.\n");
  248.     GAPrintHowTo(CtrlStr);
  249.     exit(1);
  250.     }
  251.  
  252.     GlblNormalLen = ((RealType) GlblNormalLenAux) / NORMAL_SCALER_LENGTH;
  253.  
  254.     strcpy(GlblFirstDataFileName, FileNames[0]);/* Save name of first file. */
  255.  
  256.     /* Get the data files: */
  257.     IritPrsrPolyListCirc = FALSE;
  258.     PObjects = MainGetDataFiles(FileNames, NumFiles);
  259.     if (GlblViewMode != VIEW_PERSPECTIVE)
  260.     GlblViewMode = IritPrsrWasPrspMat ? VIEW_PERSPECTIVE :
  261.                         VIEW_ORTHOGRAPHIC;
  262.  
  263.     /* If no limit on num of edges set to maximum. Else increase count by    */
  264.     /* one as we count vertices and n vertices bounds n-1 edges.         */
  265.     if (GlblNumEdges == 0)
  266.     GlblNumEdges = 32767;
  267.     else
  268.     GlblNumEdges++;
  269.  
  270. #ifdef __MSDOS__
  271.     GGInstallBGI(BGIDriverPath, SVGANameMode);
  272.     GGInitGraph(GlblGraphDriver, TRUE);      /* Initiate the graphic driver. */
  273. #else
  274. #ifdef DJGCC
  275.     GGInitGraph(0, TRUE);             /* Initiate the graphic driver. */
  276. #else
  277.     GGInitGraph(argc, argv, TRUE, TRUE);     /* Initiate the graphic driver. */
  278. #endif /* DJGCC */
  279. #endif /* __MSDOS__ */
  280.  
  281.     InteractGeomObject(PObjects);
  282.  
  283.     MyExit(0);
  284. }
  285.  
  286. /*****************************************************************************
  287. * Main routine to read the data    description files:                 *
  288. * Returns pointer to pointers on FileDescription structures (one per file).  *
  289. *****************************************************************************/
  290. static IPObjectStruct *MainGetDataFiles(char **DataFileNames, int NumOfDataFiles)
  291. {
  292.     int    i;
  293.     char *ErrorMsg;
  294.     FILE *f;
  295.     IPObjectStruct *PObj, *PObjTail,
  296.     *PObjHead = NULL;
  297.  
  298.     for    (i = 0; i < NumOfDataFiles; i++) {
  299.     if (GlblMore) fprintf(stderr, "Reading data file %s\n", *DataFileNames);
  300. #if defined(__MSDOS__) || defined(DJGCC)
  301.     if ((f = fopen(*DataFileNames, "rt")) == NULL) {   /* Open the file. */
  302. #else
  303.     if ((f = fopen(*DataFileNames, "r")) == NULL) {    /* Open the file. */
  304. #endif /* __MSDOS__ || DJGCC */
  305.         fprintf(stderr, "Can't open data file %s\n", *DataFileNames);
  306.         exit(1);
  307.     }
  308.  
  309.     if ((PObj = IritPrsrGetObjects(f)) != NULL) {  /* Get the data file. */
  310.         PObjTail = PObj;
  311.         while (PObjTail -> Pnext) PObjTail = PObjTail -> Pnext;
  312.         PObjTail -> Pnext = PObjHead;
  313.         PObjHead = PObj;
  314.     }
  315.  
  316.     if (GlblMore && IritPrsrParseError(&ErrorMsg))
  317.         fprintf(stderr, "File %s, %s\n", *DataFileNames, ErrorMsg);
  318.  
  319.     fclose(f);                      /* Close the file. */
  320.  
  321.     DataFileNames++;              /* Skip to next file name. */
  322.     }
  323.  
  324.     if (PObjHead == NULL) {
  325.     fprintf(stderr, "No data found.\n");
  326.     exit(1);
  327.     }
  328.  
  329.     return PObjHead;
  330. }
  331.  
  332. /*****************************************************************************
  333. * Routine to convert all surfaces/curves into polylines as follows:         *
  334. * Curves are converted to single polyline with SamplesPerCurve samples.         *
  335. * Surface are converted into GlblNumOfIsolines curves in each axes, each     *
  336. * handled as Curves above. The polylines are saved in the appropriate        *
  337. * surface/curve slots.                                 *
  338. *****************************************************************************/
  339. IPObjectStruct *IritPrsrProcessFreeForm(IPObjectStruct *CrvObjs,
  340.                     IPObjectStruct *SrfObjs)
  341. {
  342.     CagdCrvStruct *Crv, *Crvs;
  343.     CagdSrfStruct *Srf, *Srfs;
  344.     IPObjectStruct *PObj, *PPolyObj;
  345.     IPPolygonStruct *PPolygon, *PPolygonTemp;
  346.  
  347.     if (CrvObjs == NULL && SrfObjs == NULL) return NULL;
  348.  
  349.     /* Make sure requested format is something reasonable. */
  350.     if (GlblNumOfIsolines < 2) {
  351.     GlblNumOfIsolines = 2;
  352.     if (GlblMore)
  353.         fprintf(stderr,
  354.             "NumOfIsolines is less than 2, 2 picked instead.\n");
  355.     }
  356.  
  357.     if (GlblSamplesPerCurve < 1) {
  358.     GlblSamplesPerCurve = 1;
  359.     if (GlblMore)
  360.         fprintf(stderr,
  361.             "SamplesPerCurve is less than 1, 1 picked instead.\n");
  362.     }
  363.     if (GlblSamplesPerCurve > CAGD_MAX_BEZIER_CACHE_ORDER) {
  364.     GlblSamplesPerCurve = CAGD_MAX_BEZIER_CACHE_ORDER;
  365.     if (GlblMore)
  366.         fprintf(stderr,
  367.             "Log2 SamplesPerCurve is more than %d, %d picked instead.\n",
  368.         CAGD_MAX_BEZIER_CACHE_ORDER, CAGD_MAX_BEZIER_CACHE_ORDER);
  369.     }
  370.     BzrCrvSetCache(GlblSamplesPerCurve, TRUE);     /* Set up the bezier cache. */
  371.  
  372.     if (CrvObjs) {
  373.     for (PObj = CrvObjs; PObj != NULL; PObj = PObj -> Pnext) {
  374.         Crvs = PObj -> U.PCrvs;
  375.         PObj -> FFPolylines = PPolyObj = IritPrsrNewObjectStruct();
  376.         *PPolyObj = *PObj;            /* Copy all its attributes. */
  377.         PPolyObj -> U.PPolygon = NULL;
  378.         PPolyObj -> Type = IP_OBJ_POLY;
  379.         for (Crv = Crvs; Crv != NULL; Crv = Crv -> Pnext) {
  380.         PPolygon = PPolygonTemp = Curve2Polylines(Crv);
  381.         while (PPolygonTemp -> Pnext)
  382.             PPolygonTemp = PPolygonTemp -> Pnext;
  383.         PPolygonTemp -> Pnext = PPolyObj -> U.PPolygon;
  384.         PPolyObj -> U.PPolygon = PPolygon;
  385.         }
  386.     }
  387.     }
  388.  
  389.     if (SrfObjs) {
  390.     for (PObj = SrfObjs; PObj != NULL; PObj = PObj -> Pnext) {
  391.         Srfs = PObj -> U.PSrfs;
  392.         PObj -> FFPolylines = PPolyObj = IritPrsrNewObjectStruct();
  393.         *PPolyObj = *PObj;            /* Copy all its attributes. */
  394.         PPolyObj -> U.PPolygon = NULL;
  395.         PPolyObj -> Type = IP_OBJ_POLY;
  396.         for (Srf = Srfs; Srf != NULL; Srf = Srf -> Pnext) {
  397.         PPolygon = PPolygonTemp = Surface2Polylines(Srf);
  398.         while (PPolygonTemp -> Pnext)
  399.             PPolygonTemp = PPolygonTemp -> Pnext;
  400.         PPolygonTemp -> Pnext = PPolyObj -> U.PPolygon;
  401.         PPolyObj -> U.PPolygon = PPolygon;
  402.         }
  403.         /* IF polygons were actually created, make sure we would not     */
  404.         /* create then again...                         */
  405.         if (GlblDrawSurfacePoly)
  406.         PObj -> FFPolygons = PObj -> FFPolylines;
  407.     }
  408.     }
  409.  
  410.     if (SrfObjs == NULL)
  411.     return CrvObjs;
  412.     else if (CrvObjs == NULL)
  413.     return SrfObjs;
  414.     else {
  415.     for (PObj = SrfObjs; PObj -> Pnext != NULL; PObj = PObj -> Pnext);
  416.     PObj -> Pnext = CrvObjs;
  417.     return SrfObjs;
  418.     }
  419. }
  420.  
  421. /*****************************************************************************
  422. * Routine to convert a single curve into a polyline with SamplesPerCurve     *
  423. * samples, into a polyline object.                         *
  424. *****************************************************************************/
  425. static IPPolygonStruct *Curve2Polylines(CagdCrvStruct *Crv)
  426. {
  427.     int i, j, n;
  428.     IPVertexStruct *V,
  429.     *VHead = NULL,
  430.     *VTail = NULL;
  431.     IPPolygonStruct *P,
  432.     *PHead = NULL;
  433.     CagdPolylineStruct *CagdPoly,
  434.     *CagdPolyHead = CagdCrv2Polyline(Crv, GlblSamplesPerCurve);
  435.  
  436.     if (GlblDrawSurfaceMesh) {
  437.     CagdPoly = CagdCrv2CtrlPoly(Crv);
  438.     CagdPoly -> Pnext = CagdPolyHead;
  439.     CagdPolyHead = CagdPoly;
  440.     }
  441.  
  442.     for (CagdPoly = CagdPolyHead;
  443.      CagdPoly != NULL;
  444.      CagdPoly = CagdPoly -> Pnext) {
  445.     n = CagdPoly -> Length;
  446.  
  447.     for (i = 0, VHead = NULL; i < n; i++) {         /* Convert to vertices. */
  448.         V = IritPrsrNewVertexStruct();
  449.  
  450.         for (j = 0; j < 3; j++)              /* Convert to our format. */
  451.         V -> Coord[j] = CagdPoly -> Polyline[i].Pt[j];
  452.  
  453.         if (VHead) {
  454.         VTail -> Pnext = V;
  455.         VTail = V;
  456.         }
  457.         else
  458.         VHead = VTail = V;
  459.     }
  460.  
  461.     P = IritPrsrNewPolygonStruct();
  462.     P -> PVertex = VHead;
  463.     P -> Type = IP_POLYLINE;
  464.  
  465.     P -> Pnext = PHead;
  466.     PHead = P;
  467.     }
  468.  
  469.     CagdPolylineFreeList(CagdPoly);
  470.  
  471.     return PHead;
  472. }
  473.  
  474. #ifdef __GL__
  475.  
  476. /*****************************************************************************
  477. * Routine to convert a single surface into polygons with GlblFineNess as     *
  478. * sample control, and GlblFourPerFlat controlling # of polys per bilinear.   *
  479. *****************************************************************************/
  480. IPPolygonStruct *Surface2Polygons(CagdSrfStruct *Srf)
  481. {
  482.     int i, j;
  483.     IPVertexStruct *V, *VHead,
  484.     *VTail = NULL;
  485.     IPPolygonStruct *P,
  486.     *PHead = NULL;
  487.     CagdPolygonStruct *CagdPolygon,
  488.     *CagdPolygonHead = CagdSrf2Polygons(Srf, 1 << GlblFineNess, TRUE,
  489.                             GlblFourPerFlat);
  490.  
  491.     for (CagdPolygon = CagdPolygonHead, VHead = NULL;
  492.      CagdPolygon != NULL;
  493.      CagdPolygon = CagdPolygon -> Pnext) {
  494.     /* All polygons are triangles! */
  495.  
  496.     for (i = 0, VHead = NULL; i < 3; i++) {         /* Convert to vertices. */
  497.         V = IritPrsrNewVertexStruct();
  498.         IP_SET_VRTX_NORMAL(V);             /* This vertex has normal. */
  499.  
  500.         for (j = 0; j < 3; j++)                /* Convert to our format. */
  501.            V -> Coord[j] = CagdPolygon -> Polygon[i].Pt[j];
  502.         for (j = 0; j < 3; j++)
  503.            V -> Normal[j] = CagdPolygon -> Normal[i].Vec[j];
  504.  
  505.         if (VHead) {
  506.         VTail -> Pnext = V;
  507.         VTail = V;
  508.         }
  509.         else
  510.         VHead = VTail = V;
  511.     }
  512.  
  513.     P = IritPrsrNewPolygonStruct();
  514.     P -> PVertex = VHead;
  515.     P -> Type = IP_POLYGON;
  516.     P -> Pnext = PHead;
  517.  
  518.     PHead = P;
  519.     }
  520.  
  521.     CagdPolygonFreeList(CagdPolygonHead);
  522.  
  523.     return PHead;
  524. }
  525.  
  526. #endif /* __GL__ */
  527.  
  528. /*****************************************************************************
  529. * Routine to convert a single surface into a polylines with SamplesPerCurve  *
  530. * samples, NumOfIsolines isolines into a polyline object list.             *
  531. * If surface is to be approximated as polygons GlblFineNess and             *
  532. * GlblFourPerFlat controls this approximation.                     *
  533. *****************************************************************************/
  534. static IPPolygonStruct *Surface2Polylines(CagdSrfStruct *Srf)
  535. {
  536.     int i, j, n;
  537.     IPVertexStruct *V,
  538.     *VHead = NULL,
  539.     *VTail = NULL;
  540.     IPPolygonStruct *P,
  541.     *PHead = NULL;
  542.     CagdPolylineStruct *CagdPolyline, *CagdPolylineTemp,
  543.     *CagdPolylineHead = NULL;
  544.     CagdPolygonStruct *CagdPolygon,
  545.     *CagdPolygonHead = NULL;
  546.  
  547.     /* Note we compute normals in msdos only on demand. On unix we always   */
  548.     /* compute them as they are also used in shading.                */
  549.     if (GlblDrawSurfacePoly)
  550.     CagdPolygonHead = CagdSrf2Polygons(Srf, 1 << GlblFineNess,
  551. #if defined(__MSDOS__) || defined(DJGCC)
  552.                        GlblDrawVNormal, GlblFourPerFlat);
  553. #else
  554.                        TRUE, GlblFourPerFlat);
  555. #endif /* __MSDOS__ || DJGCC */
  556.  
  557.     else
  558.     CagdPolylineHead = CagdSrf2Polylines(Srf, GlblNumOfIsolines,
  559.                               GlblSamplesPerCurve);
  560.  
  561.     if (GlblDrawSurfaceMesh) {
  562.     CagdPolyline = CagdPolylineTemp = CagdSrf2CtrlMesh(Srf);
  563.     if (CagdPolylineTemp)
  564.         while (CagdPolylineTemp -> Pnext)
  565.         CagdPolylineTemp = CagdPolylineTemp -> Pnext;
  566.     CagdPolylineTemp -> Pnext = CagdPolylineHead;
  567.     CagdPolylineHead = CagdPolyline;
  568.     }
  569.  
  570.     for (CagdPolyline = CagdPolylineHead;
  571.      CagdPolyline != NULL;
  572.      CagdPolyline = CagdPolyline -> Pnext) {
  573.     n = CagdPolyline -> Length;
  574.  
  575.     for (i = 0, VHead = NULL; i < n; i++) {         /* Convert to vertices. */
  576.         V = IritPrsrNewVertexStruct();
  577.  
  578.         for (j = 0; j < 3; j++)                /* Convert to our format. */
  579.            V -> Coord[j] = CagdPolyline -> Polyline[i].Pt[j];
  580.  
  581.         if (VHead) {
  582.         VTail -> Pnext = V;
  583.         VTail = V;
  584.         }
  585.         else
  586.         VHead = VTail = V;
  587.     }
  588.  
  589.     P = IritPrsrNewPolygonStruct();
  590.     P -> PVertex = VHead;
  591.     P -> Type = IP_POLYLINE;
  592.     P -> Pnext = PHead;
  593.  
  594.     PHead = P;
  595.     }
  596.  
  597.     CagdPolylineFreeList(CagdPolylineHead);
  598.  
  599.     for (CagdPolygon = CagdPolygonHead, VHead = NULL;
  600.      CagdPolygon != NULL;
  601.      CagdPolygon = CagdPolygon -> Pnext) {
  602.     /* All polygons are triangles! */
  603.  
  604.     for (i = 0, VHead = NULL; i < 3; i++) {         /* Convert to vertices. */
  605.         V = IritPrsrNewVertexStruct();
  606.         IP_SET_VRTX_NORMAL(V);             /* This vertex has normal. */
  607.  
  608.         for (j = 0; j < 3; j++)                /* Convert to our format. */
  609.            V -> Coord[j] = CagdPolygon -> Polygon[i].Pt[j];
  610.         for (j = 0; j < 3; j++)
  611.            V -> Normal[j] = CagdPolygon -> Normal[i].Vec[j] * GlblNormalLen;
  612.  
  613.         if (VHead) {
  614.         VTail -> Pnext = V;
  615.         VTail = V;
  616.         }
  617.         else
  618.         VHead = VTail = V;
  619.     }
  620.  
  621.     P = IritPrsrNewPolygonStruct();
  622.     P -> PVertex = VHead;
  623.     P -> Type = IP_POLYGON;
  624.     P -> Pnext = PHead;
  625.  
  626.     PHead = P;
  627.     }
  628.  
  629.     CagdPolygonFreeList(CagdPolygonHead);
  630.  
  631.     return PHead;
  632. }
  633.  
  634. #ifdef __DEBUG_MALLOC__
  635. /*****************************************************************************
  636. * My Routine to    allocate dynamic memory. All program requests must call this *
  637. * routine (no direct call to malloc). Dies if no memory.             *
  638. *****************************************************************************/
  639. static void AllocError(const char *Msg, VoidPtr *p)
  640. {
  641.     fprintf(stderr, "%s, Ptr = %p\n", Msg, p);
  642.     MyExit(3);
  643. }
  644. #endif /* __DEBUG_MALLOC__ */
  645.  
  646. /*****************************************************************************
  647. * My Routine to    allocate dynamic memory. All program requests must call this *
  648. * routine (no direct call to malloc). Dies if no memory.             *
  649. *****************************************************************************/
  650. VoidPtr MyMalloc(unsigned size)
  651. {
  652.     static int Count = 0;
  653.     VoidPtr p;
  654.  
  655. #ifdef __MSDOS__
  656.     if (Count++ == 50) {
  657.     Count = 0;
  658.     fprintf(stderr, "Core left: %ldk   \r", coreleft() / 1024);
  659.     }
  660. #endif /* __MSDOS__ */
  661.  
  662.     if ((p = malloc(size)) != NULL) return p;
  663.  
  664.     fprintf(stderr, "Not enough memory, exit.\n");
  665.     MyExit(2);
  666.  
  667.     return NULL;                    /* Make warnings silent. */
  668. }
  669.  
  670. /*****************************************************************************
  671. * My Routine to    free dynamic memory. All program requests must call this     *
  672. * routine (no direct call to free).                         *
  673. *****************************************************************************/
  674. void MyFree(VoidPtr p)
  675. {
  676. #ifdef __DEBUG_MALLOC__
  677.     switch (heapchecknode(p)) {
  678.     case _HEAPCORRUPT:
  679.         AllocError("Heap is corrupted", p);
  680.         break;
  681.     case _BADNODE:
  682.         AllocError("Attempt to free a bogus pointer", p);
  683.         break;
  684.     case _FREEENTRY:
  685.         AllocError("Attempt to free an already freed pointer", p);
  686.         break;
  687.     case _USEDENTRY:
  688.         break;
  689.     default:
  690.         AllocError("Allocation error", p);
  691.         break;
  692.  
  693.     }
  694. #endif /* __DEBUG_MALLOC__ */
  695.  
  696.     free(p);
  697. }
  698.  
  699. /*****************************************************************************
  700. * Trap Cagd_lib errors right here.                         *
  701. *****************************************************************************/
  702. void CagdFatalError(CagdFatalErrorType ErrID)
  703. {
  704.     char
  705.     *ErrorMsg = CagdDescribeError(ErrID);
  706.  
  707.     GGCloseGraph();                /* Close the graphic driver. */
  708.  
  709.     fprintf(stderr, "CAGD_LIB: %s", ErrorMsg);
  710.  
  711.     exit(-1);
  712. }
  713.  
  714. /*****************************************************************************
  715. * My exit routine.                                 *
  716. *****************************************************************************/
  717. void MyExit(int ExitCode)
  718. {
  719.     GGCloseGraph();                /* Close the graphic driver. */
  720.  
  721. #ifdef __MSDOS__
  722.     fprintf(stderr,
  723.         "\nPoly3D: Total RealTime %ld seconds, Core left %ldk.\n",
  724.         time(NULL) - SaveTotalTime, coreleft() / 1024);
  725. #else
  726.     fprintf(stderr,
  727.         "\nPoly3D: Total RealTime %ld seconds.\n",
  728.         time(NULL) - SaveTotalTime);
  729. #endif /* __MSDOS__ */
  730.  
  731.     exit(ExitCode);
  732. }
  733.